<template>
  <!--Dialog-->
  <Dialog v-model="modelValue">
    <el-form :inline="true" label-width="auto">
      <el-row>
        <el-col :span="24">
          <el-form-item label="名称">
            {{ updateForm.name }}
          </el-form-item>
          <el-form-item label="是否公开">
            <el-switch v-model="updateForm.isPublic" :disabled="true" />
          </el-form-item>
          <el-form-item label="是否默认">
            <el-switch v-model="updateForm.isDefault" :disabled="true" /> </el-form-item
        ></el-col>
        <el-col :span="24">
          <el-form-item label="角色权限">
            <el-tree
              class="el-tree"
              :data="trees"
              :render-content="renderContent"
              :show-checkbox="true"
              node-key="id"
              ref="treeRef"
              :highlight-current="true"
              :default-expand-all="true"
              @node-expand="handleExpand"
              :props="defaultProps"
            ></el-tree>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <el-button @click="onClose">关闭</el-button>
    </template>
  </Dialog>
</template>

<script setup lang="ts">
import { reqPermissionAll } from '@/utils/api/permission/index';
import { getAsync, getPermissionListAsync } from '@/utils/api/role/index';
import { Dialog } from '@/components/dialog/index';
import { propTypes } from '@/utils/propTypes';
import { onMounted, ref, nextTick } from 'vue';
import type { ElTree } from 'element-plus';
import type { IdentityRoleDto } from '@/utils/api/role/type';
import { PermissionType, type PermissionTreeDto } from '@/utils/api/permission/type';

const props = defineProps({
  id: propTypes.string
});

// 控制组件隐藏与显示
const modelValue = defineModel<boolean>(propTypes.bool.def(false));
const close = () => {
  modelValue.value = false;
};

// tree组件实例对象
const treeRef = ref<InstanceType<typeof ElTree>>();

//组件挂载完毕
onMounted(async () => {
  // 加载权限
  await initAllPermissionAsync();

  // 加载角色权限
  await initRolePermission();

  // 更改tree按钮横向样式
  changeCss();

  // 根据id绑定角色数据
  await initRoleAsync();

  // 记录之前的选中数据
  initDefaultCheckedkeys();
});

// 权限PermissionTreeDt转化成Tree数组
const getSeletcPermission = (permissions: Array<PermissionTreeDto>): Array<Tree> => {
  let arrays = new Array<Tree>();
  permissions.forEach((item) => {
    let tree: Tree = {
      id: item.name,
      label: item.displayName!,
      disabled: true,
      isFloat: item.type == PermissionType.Button
    };
    if (item.childPermissions && item.childPermissions.length > 0) {
      tree.children = getSeletcPermission(item.childPermissions);
    }
    arrays.push(tree);
  });
  return arrays;
};

// 加载角色信息
const initRoleAsync = async () => {
  updateForm.value = await getAsync(props.id);
};

// 加载角色权限
const beforePermissions: Array<string> = [];
const initRolePermission = async () => {
  // 设置节点选中
  const checkedkeys = await getPermissionListAsync(props.id);
  for (let index = 0; index < checkedkeys.length; index++) {
    const item = checkedkeys[index];
    treeRef.value!.setChecked(item, true, false);
  }
};

// 加载操作前选中数据
const initDefaultCheckedkeys = () => {
  const checkedNodes = treeRef.value!.getCheckedNodes(false, true);
  for (let index = 0; index < checkedNodes.length; index++) {
    const item = checkedNodes[index];
    beforePermissions.push(item.id);
  }
};

// 加载权限
const initAllPermissionAsync = async () => {
  const data = await reqPermissionAll();
  const treeData = getSeletcPermission(data);
  trees.value = treeData;
};

// 根据角色加载权限

// 关闭
const onClose = () => {
  //触发自定义事件
  close();
};

// 添加角色对象
const updateForm = ref<IdentityRoleDto>({
  id: '',
  name: '',
  isPublic: false,
  isDefault: false,
  isStatic: false
});

// 数据对象
const defaultProps = {
  children: 'children',
  label: 'label',
  disabled: 'disabled'
};

// Tree
interface Tree {
  id: string;
  label: string;
  isFloat?: boolean;
  disabled?: boolean;
  children?: Tree[];
}

// 权限数据
const trees = ref<Array<Tree>>([]);

// 更新树的css
const changeCss = () => {
  let levelNames = document.getElementsByClassName('foo'); // levelname是上面的最底层节点的名字
  for (let i = 0; i < levelNames.length; i++) {
    // cssFloat 兼容 ie6-8  styleFloat 兼容ie9及标准浏览器
    let levelName = levelNames[i].parentNode?.parentNode as HTMLElement;
    levelName.style.cssFloat = 'left'; // 最底层的节点，包括多选框和名字都让他左浮动
    //levelName.style.width = '240px'
  }
};

// tree renderContent
const renderContent = (
  h: any,
  {
    data
  }: {
    data: Tree;
  }
) => {
  //树节点的内容区的渲染 Function
  let classname = '';
  // 由于项目中有三级菜单也有四级级菜单，就要在此做出判断
  if (data.isFloat) {
    classname = 'foo';
  }
  return h(
    'div',
    {
      class: classname
    },
    data.label
  );
};

// 节点被展开时触发的事件
const handleExpand = () => {
  //节点被展开时触发的事件
  //因为该函数执行在renderContent函数之前，所以得加this.$nextTick()
  nextTick(() => {
    changeCss();
  });
};
</script>
<style scoped lang="scss"></style>
